<!DOCTYPE html>
<html style="display: none;" lang="zh">
    <head><meta name="generator" content="Hexo 3.9.0">
    <meta charset="utf-8">
    <!--
        © Material Theme
        https://github.com/viosey/hexo-theme-material
        Version: 1.5.6 -->
    <script>
        window.materialVersion = "1.5.6"
        // Delete localstorage with these tags
        window.oldVersion = [
            'codestartv1',
            '1.3.4',
            '1.4.0',
            '1.4.0b1',
            '1.5.0',
            '1.5.2',
            '1.5.5'
        ]
    </script>

    <!-- dns prefetch -->
    <meta http-equiv="x-dns-prefetch-control" content="on">









    <link rel="dns-prefetch" href="https://fonts.googleapis.com">





    <!-- Meta & Info -->
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">

    <!-- Title -->
    
    <title>
        
            gitlab CI/CD与线上k8s环境集成 | 
        
        Noir的博客
    </title>

    <!-- Favicons -->
    <link rel="icon shortcut" type="image/ico" href="/rubin-blog/img/logo.png">
    <link rel="icon" href="/rubin-blog/img/logo.png">

    <meta name="format-detection" content="telephone=no">
    <meta name="description" itemprop="description" content="今天也要加油鸭！！！">
    <meta name="keywords" content=",kubernetes,CI/CD,gitlab">
    <meta name="theme-color" content="#0097A7">

    <!-- Disable Fucking Bloody Baidu Tranformation -->
    <meta http-equiv="Cache-Control" content="no-transform">
    <meta http-equiv="Cache-Control" content="no-siteapp">

    <!--[if lte IE 9]>
        <link rel="stylesheet" href="/css/ie-blocker.css">

        
            <script src="/js/ie-blocker.zhCN.js"></script>
        
    <![endif]-->

    <!-- Import lsloader -->
    <script>(function(){window.lsloader={jsRunSequence:[],jsnamemap:{},cssnamemap:{}};lsloader.removeLS=function(a){try{localStorage.removeItem(a)}catch(b){}};lsloader.setLS=function(a,c){try{localStorage.setItem(a,c)}catch(b){}};lsloader.getLS=function(a){var c="";try{c=localStorage.getItem(a)}catch(b){c=""}return c};versionString="/*"+(window.materialVersion||"unknownVersion")+"*/";lsloader.clean=function(){try{var b=[];for(var a=0;a<localStorage.length;a++){b.push(localStorage.key(a))}b.forEach(function(e){var f=lsloader.getLS(e);if(window.oldVersion){var d=window.oldVersion.reduce(function(g,h){return g||f.indexOf("/*"+h+"*/")!==-1},false);if(d){lsloader.removeLS(e)}}})}catch(c){}};lsloader.clean();lsloader.load=function(f,a,b,d){if(typeof b==="boolean"){d=b;b=undefined}d=d||false;b=b||function(){};var e;e=this.getLS(f);if(e&&e.indexOf(versionString)===-1){this.removeLS(f);this.requestResource(f,a,b,d);return}if(e){var c=e.split(versionString)[0];if(c!=a){console.log("reload:"+a);this.removeLS(f);this.requestResource(f,a,b,d);return}e=e.split(versionString)[1];if(d){this.jsRunSequence.push({name:f,code:e});this.runjs(a,f,e)}else{document.getElementById(f).appendChild(document.createTextNode(e));b()}}else{this.requestResource(f,a,b,d)}};lsloader.requestResource=function(b,e,a,c){var d=this;if(c){this.iojs(e,b,function(h,f,g){d.setLS(f,h+versionString+g);d.runjs(h,f,g)})}else{this.iocss(e,b,function(f){document.getElementById(b).appendChild(document.createTextNode(f));d.setLS(b,e+versionString+f)},a)}};lsloader.iojs=function(d,b,g){var a=this;a.jsRunSequence.push({name:b,code:""});try{var f=new XMLHttpRequest();f.open("get",d,true);f.onreadystatechange=function(){if(f.readyState==4){if((f.status>=200&&f.status<300)||f.status==304){if(f.response!=""){g(d,b,f.response);return}}a.jsfallback(d,b)}};f.send(null)}catch(c){a.jsfallback(d,b)}};lsloader.iocss=function(f,c,h,a){var b=this;try{var g=new XMLHttpRequest();g.open("get",f,true);g.onreadystatechange=function(){if(g.readyState==4){if((g.status>=200&&g.status<300)||g.status==304){if(g.response!=""){h(g.response);a();return}}b.cssfallback(f,c,a)}};g.send(null)}catch(d){b.cssfallback(f,c,a)}};lsloader.iofonts=function(f,c,h,a){var b=this;try{var g=new XMLHttpRequest();g.open("get",f,true);g.onreadystatechange=function(){if(g.readyState==4){if((g.status>=200&&g.status<300)||g.status==304){if(g.response!=""){h(g.response);a();return}}b.cssfallback(f,c,a)}};g.send(null)}catch(d){b.cssfallback(f,c,a)}};lsloader.runjs=function(f,c,e){if(!!c&&!!e){for(var b in this.jsRunSequence){if(this.jsRunSequence[b].name==c){this.jsRunSequence[b].code=e}}}if(!!this.jsRunSequence[0]&&!!this.jsRunSequence[0].code&&this.jsRunSequence[0].status!="failed"){var a=document.createElement("script");a.appendChild(document.createTextNode(this.jsRunSequence[0].code));a.type="text/javascript";document.getElementsByTagName("head")[0].appendChild(a);this.jsRunSequence.shift();if(this.jsRunSequence.length>0){this.runjs()}}else{if(!!this.jsRunSequence[0]&&this.jsRunSequence[0].status=="failed"){var d=this;var a=document.createElement("script");a.src=this.jsRunSequence[0].path;a.type="text/javascript";this.jsRunSequence[0].status="loading";a.onload=function(){d.jsRunSequence.shift();if(d.jsRunSequence.length>0){d.runjs()}};document.body.appendChild(a)}}};lsloader.tagLoad=function(b,a){this.jsRunSequence.push({name:a,code:"",path:b,status:"failed"});this.runjs()};lsloader.jsfallback=function(c,b){if(!!this.jsnamemap[b]){return}else{this.jsnamemap[b]=b}for(var a in this.jsRunSequence){if(this.jsRunSequence[a].name==b){this.jsRunSequence[a].code="";this.jsRunSequence[a].status="failed";this.jsRunSequence[a].path=c}}this.runjs()};lsloader.cssfallback=function(e,c,b){if(!!this.cssnamemap[c]){return}else{this.cssnamemap[c]=1}var d=document.createElement("link");d.type="text/css";d.href=e;d.rel="stylesheet";d.onload=d.onerror=b;var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(d,a)};lsloader.runInlineScript=function(c,b){var a=document.getElementById(b).innerText;this.jsRunSequence.push({name:c,code:a});this.runjs()}})();</script>

    <!-- Import queue -->
    <script>function Queue(){this.dataStore=[];this.offer=b;this.poll=d;this.execNext=a;this.debug=false;this.startDebug=c;function b(e){if(this.debug){console.log("Offered a Queued Function.")}if(typeof e==="function"){this.dataStore.push(e)}else{console.log("You must offer a function.")}}function d(){if(this.debug){console.log("Polled a Queued Function.")}return this.dataStore.shift()}function a(){var e=this.poll();if(e!==undefined){if(this.debug){console.log("Run a Queued Function.")}e()}}function c(){this.debug=true}}var queue=new Queue();</script>

    <!-- Import CSS -->
    
        <style id="material_css"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("material_css","/rubin-blog/css/material.min.css?Z7a72R1E4SxzBKR/WGctOA==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>
        <style id="style_css"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("style_css","/rubin-blog/css/style.min.css?H1y3uLZ/l25Ii7j0fWHmRw==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>

        

    

    

    <!-- Config CSS -->

<!-- Other Styles -->
<style>
  body, html {
    font-family: Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
    overflow-x: hidden !important;
  }
  
  code {
    font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
  }

  a {
    color: #00838F;
  }

  .mdl-card__media,
  #search-label,
  #search-form-label:after,
  #scheme-Paradox .hot_tags-count,
  #scheme-Paradox .sidebar_archives-count,
  #scheme-Paradox .sidebar-colored .sidebar-header,
  #scheme-Paradox .sidebar-colored .sidebar-badge{
    background-color: #0097A7 !important;
  }

  /* Sidebar User Drop Down Menu Text Color */
  #scheme-Paradox .sidebar-colored .sidebar-nav>.dropdown>.dropdown-menu>li>a:hover,
  #scheme-Paradox .sidebar-colored .sidebar-nav>.dropdown>.dropdown-menu>li>a:focus {
    color: #0097A7 !important;
  }

  #post_entry-right-info,
  .sidebar-colored .sidebar-nav li:hover > a,
  .sidebar-colored .sidebar-nav li:hover > a i,
  .sidebar-colored .sidebar-nav li > a:hover,
  .sidebar-colored .sidebar-nav li > a:hover i,
  .sidebar-colored .sidebar-nav li > a:focus i,
  .sidebar-colored .sidebar-nav > .open > a,
  .sidebar-colored .sidebar-nav > .open > a:hover,
  .sidebar-colored .sidebar-nav > .open > a:focus,
  #ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-head a {
    color: #0097A7 !important;
  }

  .toTop {
    background: #757575 !important;
  }

  .material-layout .material-post>.material-nav,
  .material-layout .material-index>.material-nav,
  .material-nav a {
    color: #757575;
  }

  #scheme-Paradox .MD-burger-layer {
    background-color: #757575;
  }

  #scheme-Paradox #post-toc-trigger-btn {
    color: #757575;
  }

  .post-toc a:hover {
    color: #00838F;
    text-decoration: underline;
  }

</style>


<!-- Theme Background Related-->

    <style>
      body{
        background-color: #F5F5F5;
      }

      /* blog_info bottom background */
      #scheme-Paradox .material-layout .something-else .mdl-card__supporting-text{
        background-color: #fff;
      }
    </style>




<!-- Fade Effect -->

    <style>
      .fade {
        transition: all 800ms linear;
        -webkit-transform: translate3d(0,0,0);
        -moz-transform: translate3d(0,0,0);
        -ms-transform: translate3d(0,0,0);
        -o-transform: translate3d(0,0,0);
        transform: translate3d(0,0,0);
        opacity: 1;
      }

      .fade.out{
        opacity: 0;
      }
    </style>


<!-- Import Font -->
<!-- Import Roboto -->

    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">


<!-- Import Material Icons -->


    <style id="material_icons"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("material_icons","/rubin-blog/css/material-icons.css?pqhB/Rd/ab0H2+kZp0RDmw==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>




    <!-- Import jQuery -->
    
        <script>lsloader.load("jq_js","/rubin-blog/js/jquery.min.js?ezyEvm8ST5CGfpA+kFFi1g==", true)</script>
    

    <!-- WebAPP Icons -->
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="application-name" content="Noir的博客">
    <meta name="msapplication-starturl" content="https://achacha.gitee.io/rubin-blog/rubin-blog/2019/11/04/gilab-CI-CD与线上k8s环境集成/">
    <meta name="msapplication-navbutton-color" content="#0097A7">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-title" content="Noir的博客">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="apple-touch-icon" href="/rubin-blog/img/logo.png">

    <!-- Site Verification -->
    
    

    <!-- RSS -->
    

    <!-- The Open Graph protocol -->
    <meta property="og:url" content="https://achacha.gitee.io/rubin-blog/rubin-blog/2019/11/04/gilab-CI-CD与线上k8s环境集成/">
    <meta property="og:type" content="blog">
    <meta property="og:title" content="gitlab CI/CD与线上k8s环境集成 | Noir的博客">
    <meta property="og:image" content="/rubin-blog/img/logo.png">
    <meta property="og:description" content="今天也要加油鸭！！！">
    <meta property="og:article:tag" content="kubernetes"> <meta property="og:article:tag" content="CI/CD"> <meta property="og:article:tag" content="gitlab"> 

    
        <meta property="article:published_time" content="Mon Nov 04 2019 13:30:24 GMT+0800">
        <meta property="article:modified_time" content="Wed May 06 2020 21:37:48 GMT+0800">
    

    <!-- The Twitter Card protocol -->
    <meta name="twitter:card" content="summary_large_image">

    <!-- Add canonical link for SEO -->
    
        <link rel="canonical" href="https://achacha.gitee.io/rubin-blog/rubin-blog/2019/11/04/gilab-CI-CD与线上k8s环境集成/index.html">
    

    <!-- Structured-data for SEO -->
    
        


<script type="application/ld+json">
{
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "mainEntityOfPage": "https://achacha.gitee.io/rubin-blog/rubin-blog/2019/11/04/gilab-CI-CD与线上k8s环境集成/index.html",
    "headline": "gitlab CI/CD与线上k8s环境集成",
    "datePublished": "Mon Nov 04 2019 13:30:24 GMT+0800",
    "dateModified": "Wed May 06 2020 21:37:48 GMT+0800",
    "author": {
        "@type": "Person",
        "name": "noir",
        "image": {
            "@type": "ImageObject",
            "url": "/img/avatar.jpg"
        },
        "description": "Freiheit als Autonomie"
    },
    "publisher": {
        "@type": "Organization",
        "name": "Noir的博客",
        "logo": {
            "@type":"ImageObject",
            "url": "/img/logo.png"
        }
    },
    "keywords": ",kubernetes,CI/CD,gitlab",
    "description": "今天也要加油鸭！！！",
}
</script>


    

    <!-- Analytics -->
    
    
    

    <!-- Custom Head -->
    

</head>


    
        <body id="scheme-Paradox" class="lazy">
            <div class="material-layout  mdl-js-layout has-drawer is-upgraded">
                

                <!-- Main Container -->
                <main class="material-layout__content" id="main">

                    <!-- Top Anchor -->
                    <div id="top"></div>

                    
                        <!-- Hamburger Button -->
                        <button class="MD-burger-icon sidebar-toggle">
                            <span id="MD-burger-id" class="MD-burger-layer"></span>
                        </button>
                    

                    <!-- Post TOC -->

    
    <!-- Back Button -->
    <!--
    <div class="material-back" id="backhome-div" tabindex="0">
        <a class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon"
           href="#" onclick="window.history.back();return false;"
           target="_self"
           role="button"
           data-upgraded=",MaterialButton,MaterialRipple">
            <i class="material-icons" role="presentation">arrow_back</i>
            <span class="mdl-button__ripple-container">
                <span class="mdl-ripple"></span>
            </span>
        </a>
    </div>
    -->


    <!-- Left aligned menu below button -->
    
    
    <button id="post-toc-trigger-btn"
        class="mdl-button mdl-js-button mdl-button--icon">
        <i class="material-icons">format_list_numbered</i>
    </button>

    <ul class="post-toc-wrap mdl-menu mdl-menu--bottom-left mdl-js-menu mdl-js-ripple-effect" for="post-toc-trigger-btn" style="max-height:80vh; overflow-y:scroll;">
        <ol class="post-toc"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#概述"><span class="post-toc-number">1.</span> <span class="post-toc-text">概述</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#搭建docker-registry并与docker-runner-集成"><span class="post-toc-number">2.</span> <span class="post-toc-text">搭建docker-registry并与docker runner 集成</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#配置kubernetes的runner环境变量"><span class="post-toc-number">2.1.</span> <span class="post-toc-text">配置kubernetes的runner环境变量</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#安装helm-tiller"><span class="post-toc-number">2.2.</span> <span class="post-toc-text">安装helm/tiller</span></a></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#kubernetes与pipeline"><span class="post-toc-number">3.</span> <span class="post-toc-text">kubernetes与pipeline</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#打包"><span class="post-toc-number">3.1.</span> <span class="post-toc-text">打包</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#测试"><span class="post-toc-number">3.2.</span> <span class="post-toc-text">测试</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#staging发布"><span class="post-toc-number">3.3.</span> <span class="post-toc-text">staging发布</span></a></li><li class="post-toc-item post-toc-level-3"><a class="post-toc-link" href="#滚动发布"><span class="post-toc-number">3.4.</span> <span class="post-toc-text">滚动发布</span></a></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#关于-gitlab-ci-yaml"><span class="post-toc-number">4.</span> <span class="post-toc-text">关于.gitlab-ci.yaml</span></a></li></ol>
    </ul>
    




<!-- Layouts -->

    <!-- Post Module -->
    <div class="material-post_container">

        <div class="material-post mdl-grid">
            <div class="mdl-card mdl-shadow--4dp mdl-cell mdl-cell--12-col">

                <!-- Post Header(Thumbnail & Title) -->
                
    <!-- Paradox Post Header -->
    
        
            <!-- Random Thumbnail -->
            <div class="post_thumbnail-random mdl-card__media mdl-color-text--grey-50">
            <script type="text/ls-javascript" id="post-thumbnail-script">
    var randomNum = Math.floor(Math.random() * 19 + 1);

    $('.post_thumbnail-random').attr('data-original', '/rubin-blog/img/random/material-' + randomNum + '.png');
    $('.post_thumbnail-random').addClass('lazy');
</script>

        
    
            <p class="article-headline-p">
                gitlab CI/CD与线上k8s环境集成
            </p>
        </div>





                
                    <!-- Paradox Post Info -->
                    <div class="mdl-color-text--grey-700 mdl-card__supporting-text meta">

    <!-- Author Avatar -->
    <div id="author-avatar">
        <img src="/rubin-blog/img/avatar.jpg" width="44px" height="44px" alt="Author Avatar"/>
    </div>
    <!-- Author Name & Date -->
    <div>
        <strong>noir</strong>
        <span>11月 04, 2019</span>
    </div>

    <div class="section-spacer"></div>

    <!-- Favorite -->
    <!--
        <button id="article-functions-like-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon btn-like">
            <i class="material-icons" role="presentation">favorite</i>
            <span class="visuallyhidden">favorites</span>
        </button>
    -->

    <!-- Qrcode -->
    

    <!-- Tags (bookmark) -->
    
    <button id="article-functions-viewtags-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
        <i class="material-icons" role="presentation">bookmark</i>
        <span class="visuallyhidden">bookmark</span>
    </button>
    <ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="article-functions-viewtags-button">
        <li class="mdl-menu__item">
        <a class="post_tag-link" href="/rubin-blog/tags/CI-CD/">CI/CD</a></li><li class="mdl-menu__item"><a class="post_tag-link" href="/rubin-blog/tags/gitlab/">gitlab</a></li><li class="mdl-menu__item"><a class="post_tag-link" href="/rubin-blog/tags/kubernetes/">kubernetes</a>
    </ul>
    

    <!-- Share -->
    
        <button id="article-fuctions-share-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
    <i class="material-icons" role="presentation">share</i>
    <span class="visuallyhidden">share</span>
</button>
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="article-fuctions-share-button">
    

    

    <!-- Share Weibo -->
    
        <a class="post_share-link" href="http://service.weibo.com/share/share.php?appkey=&title=gitlab CI/CD与线上k8s环境集成&url=https://achacha.gitee.io/rubin-blog/rubin-blog/2019/11/04/gilab-CI-CD与线上k8s环境集成/index.html&pic=https://achacha.gitee.io/rubin-blog/img/logo.png&searchPic=false&style=simple" target="_blank">
            <li class="mdl-menu__item">
                分享到微博
            </li>
        </a>
    

    <!-- Share Twitter -->
    
        <a class="post_share-link" href="https://twitter.com/intent/tweet?text=gitlab CI/CD与线上k8s环境集成&url=https://achacha.gitee.io/rubin-blog/rubin-blog/2019/11/04/gilab-CI-CD与线上k8s环境集成/index.html&via=noir" target="_blank">
            <li class="mdl-menu__item">
                分享到 Twitter
            </li>
        </a>
    

    <!-- Share Facebook -->
    
        <a class="post_share-link" href="https://www.facebook.com/sharer/sharer.php?u=https://achacha.gitee.io/rubin-blog/rubin-blog/2019/11/04/gilab-CI-CD与线上k8s环境集成/index.html" target="_blank">
            <li class="mdl-menu__item">
                分享到 Facebook
            </li>
        </a>
    

    <!-- Share Google+ -->
    
        <a class="post_share-link" href="https://plus.google.com/share?url=https://achacha.gitee.io/rubin-blog/rubin-blog/2019/11/04/gilab-CI-CD与线上k8s环境集成/index.html" target="_blank">
            <li class="mdl-menu__item">
                分享到 Google+
            </li>
        </a>
    

    <!-- Share LinkedIn -->
    

    <!-- Share QQ -->
    

    <!-- Share Telegram -->
    
</ul>

    
</div>

                

                <!-- Post Content -->
                <div id="post-content" class="mdl-color-text--grey-700 mdl-card__supporting-text fade out">
    
        <h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p>  依赖k8s做集成测试和持续的版本交付，并与gitlab runner集成，实现提交merge request即提测，上master后自动release。本文将从以下几步简述实现过程：</p>
<ul>
<li>私有docker registry搭建并与docker runner集成</li>
<li>kubernetes与pipeline</li>
<li>helm发布和istio做滚动发布的流控</li>
</ul>
<h2 id="搭建docker-registry并与docker-runner-集成"><a href="#搭建docker-registry并与docker-runner-集成" class="headerlink" title="搭建docker-registry并与docker runner 集成"></a>搭建docker-registry并与docker runner 集成</h2><p>  首先，docker-registry作为我们容器镜像的仓库，对于生产环境来说自然是架设在同一子网来说比较合适，不然在发布版本后的新容器创建时会出奇的慢并且会占用网络，而对于我们日常的集成测试，则需要在我们的开发平台同一子网下架设。拓扑如下：<br>  <img src="struct.png" alt="struct"></p>
<h3 id="配置kubernetes的runner环境变量"><a href="#配置kubernetes的runner环境变量" class="headerlink" title="配置kubernetes的runner环境变量"></a>配置kubernetes的runner环境变量</h3><p>  配置k8s的runner环境变量有两种方式：</p>
<ul>
<li>页面添加配置<br>在项目operations-&gt;kubenetes下添加配置</li>
<li>在环境变量中添加kubeconfig文件<br>在ci中将文件移动到.kube/config（若gitlab版本过低可以将环境配置echo至该文件）  </li>
</ul>
<p>配置好环境变量后，打包一个带有kubectl的镜像推到开发registry后，使用pipeline时既可以通过该基础镜像进行k8s的操作了。</p>
<h3 id="安装helm-tiller"><a href="#安装helm-tiller" class="headerlink" title="安装helm/tiller"></a>安装helm/tiller</h3><p>单纯的使用kubectl肯定不满足我们编排的需求，可以安装helm/tiller并打包helm开发镜像使用helm对应用进行发布。  </p>
<ol>
<li><p>下载安装helm在本地</p>
</li>
<li><p>配置好.kube/config</p>
</li>
<li><p>rbac配置（未开启可跳过该步骤）</p>
 <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"># vim tiller-clusterrolebinding.yaml</span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: ServiceAccount</span><br><span class="line">metadata:</span><br><span class="line">  name: tiller</span><br><span class="line">  namespace: kube-system</span><br><span class="line">---</span><br><span class="line">apiVersion: rbac.authorization.k8s.io/v1</span><br><span class="line">kind: ClusterRoleBinding</span><br><span class="line">metadata:</span><br><span class="line">  name: tiller</span><br><span class="line">roleRef:</span><br><span class="line">  apiGroup: rbac.authorization.k8s.io</span><br><span class="line">  kind: ClusterRole</span><br><span class="line">  name: cluster-admin</span><br><span class="line">subjects:</span><br><span class="line">  - kind: ServiceAccount</span><br><span class="line">    name: tiller</span><br><span class="line">    namespace: kube-system</span><br><span class="line">  </span><br><span class="line">#kubectl apply -f tiller-clusterrolebinding.yaml</span><br></pre></td></tr></table></figure>
</li>
<li><p>安装tiller</p>
 <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">helm init --service-account tiller --upgrade --tiller-image=registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.14.1</span><br></pre></td></tr></table></figure>
</li>
<li><p>打包helm镜像至开发registry备后续helm部署使用</p>
</li>
</ol>
<h2 id="kubernetes与pipeline"><a href="#kubernetes与pipeline" class="headerlink" title="kubernetes与pipeline"></a>kubernetes与pipeline</h2><p>  在与kubernetes集成前，我们以一个敏捷开发涉及到涉及到打包、测试、staging发布、滚动发布的pipeline来举例说明。<br>  .gitlab-ci.yaml中定义：<br>  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">stages:</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">build</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">test</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">publish</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">staging</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">rollin</span></span><br></pre></td></tr></table></figure></p>
<h3 id="打包"><a href="#打包" class="headerlink" title="打包"></a>打包</h3><p>  可以通过指定的基础镜像提供的环境将源码程序打包，如通过gradle镜像将springboot项目打包成可运行jar包：<br>  <img src="buildJob.png" alt="buildJob">  </p>
<p>  gitlab-ci.yaml中定义：<br>  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">build_jar:</span></span><br><span class="line">  <span class="attr">stage:</span> <span class="string">build</span></span><br><span class="line">  <span class="attr">image:</span> <span class="string">registry.local/gradle:latest</span></span><br><span class="line">  <span class="attr">script:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">echo</span> <span class="string">-e</span> <span class="string">"\nspring.profiles.active=prod"</span> <span class="string">&gt;&gt;</span> <span class="string">src/main/resources/application.properties</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">gradle</span> <span class="string">-g</span> <span class="string">./.cache</span> <span class="string">bootJar</span></span><br><span class="line">  <span class="attr">cache:</span></span><br><span class="line">    <span class="attr">paths:</span> </span><br><span class="line">      <span class="bullet">-</span> <span class="string">./.cache</span></span><br><span class="line">    <span class="comment"># keep cache across branch</span></span><br><span class="line">    <span class="attr">key:</span> <span class="string">gradle</span></span><br><span class="line">  <span class="attr">artifacts:</span></span><br><span class="line">    <span class="attr">paths:</span> <span class="string">[build/libs/t1-api-cert.jar]</span></span><br><span class="line">  <span class="attr">retry:</span></span><br><span class="line">    <span class="number">2</span></span><br></pre></td></tr></table></figure></p>
<h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><p>  这里主要指集成测试，在拥有docker环境时，我们可以创建相应的服务容器（如mysql、redis等）提供集成测试：<br>  <img src="testJob.png" alt="testJob"></p>
<p>  gitlab-ci.yaml中定义：<br>  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">unit_test:</span></span><br><span class="line"><span class="attr">stage:</span> <span class="string">test</span></span><br><span class="line"><span class="attr">image:</span> <span class="string">registry.local/gradle:latest</span></span><br><span class="line"><span class="attr">script:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">gradle</span> <span class="string">-g</span> <span class="string">./.cache</span> <span class="string">test</span> <span class="string">--info</span></span><br><span class="line"><span class="attr">variables:</span></span><br><span class="line">  <span class="attr">MYSQL_DATABASE:</span> <span class="string">test</span></span><br><span class="line">  <span class="attr">MYSQL_ROOT_PASSWORD:</span> <span class="string">Ok36369ok</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">name:</span> <span class="string">registry.local/mysql</span></span><br><span class="line">  <span class="attr">alias:</span> <span class="string">mysql</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">redis:latest</span></span><br><span class="line"><span class="attr">retry:</span></span><br><span class="line">  <span class="number">2</span></span><br><span class="line"><span class="attr">cache:</span></span><br><span class="line">  <span class="attr">paths:</span> </span><br><span class="line">    <span class="bullet">-</span> <span class="string">./.cache</span></span><br><span class="line">  <span class="comment"># keep cache across branch</span></span><br><span class="line">  <span class="attr">key:</span> <span class="string">gradle</span></span><br></pre></td></tr></table></figure></p>
<h3 id="staging发布"><a href="#staging发布" class="headerlink" title="staging发布"></a>staging发布</h3><p>  stage环境为了更好的测试真实的网络环境，建议部署在生产下（可以创建一个新的namespace来放这些容器），而真实环境根据不同的应用架构将有不同的拓扑与部署方案，这里仅举例一个简单的单块应用的helm部署：<br>  <img src="staging.png" alt="staging"><br>  <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">publish_image:</span></span><br><span class="line">  <span class="attr">stage:</span> <span class="string">publish</span></span><br><span class="line">  <span class="attr">image:</span> <span class="string">registry.local/dind:latest</span></span><br><span class="line">  <span class="attr">script:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">docker</span> <span class="string">build</span> <span class="string">-t="repository.prod/app:v1.0.1"</span> <span class="string">.</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">docker</span> <span class="string">push</span> <span class="string">repository.prod/app:v1.0.1</span></span><br><span class="line">  <span class="attr">retry:</span></span><br><span class="line">    <span class="number">2</span></span><br><span class="line"><span class="attr">deploy_stage:</span></span><br><span class="line">  <span class="attr">stage:</span> <span class="string">staging</span></span><br><span class="line">  <span class="attr">image:</span> <span class="string">registry.local/helm:latest</span></span><br><span class="line">  <span class="attr">script:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">helm</span> <span class="string">upgrade</span> <span class="string">--tiller-namespace</span> <span class="string">kube-system</span> <span class="string">deploy-$CI_PROJECT_NAME</span> <span class="string">chart/</span> <span class="string">--install</span> <span class="string">\</span></span><br><span class="line">      <span class="string">--wait</span> <span class="string">\</span></span><br><span class="line">      <span class="string">--set</span> <span class="string">hosts[0]="$PRODUCT_HOST"</span> <span class="string">\</span></span><br><span class="line">      <span class="string">--set</span> <span class="string">appLabel="$CI_PROJECT_NAME"</span> <span class="string">\</span></span><br><span class="line">      <span class="string">--set</span> <span class="string">containerPort=$CONTAINER_PORT</span> <span class="string">\</span></span><br><span class="line">      <span class="string">--set</span> <span class="string">replicaCount=$replicas</span> <span class="string">\</span></span><br><span class="line">      <span class="string">--set</span> <span class="string">image.repository=repository.prod/app:v1.0.1</span> <span class="string">\</span></span><br><span class="line">      <span class="string">--namespace="$KUBE_NAMESPACE"</span> <span class="string">\</span></span><br><span class="line">      <span class="string">--version="$CI_PIPELINE_ID-$CI_COMMIT_SHA"</span>  </span><br><span class="line">  <span class="attr">retry:</span></span><br><span class="line">    <span class="number">2</span></span><br></pre></td></tr></table></figure></p>
<p>  其中的各个参数是自定义chart中规定的，可以根据具体项目及团队习惯进行定制修改并添加功能，比如滚动发布就只需要集成对应的istio的yaml配置并暴露出对应的VALUES配置来进行流量控制。</p>
<h3 id="滚动发布"><a href="#滚动发布" class="headerlink" title="滚动发布"></a>滚动发布</h3><p>  在生产部署中，我们可能会采用各种策略来实现版本发布，如金丝雀、灰度（滚动）发布等，咱们可以在helm charts中定义好实现方式，如使用istio的router-rule实现。</p>
<h2 id="关于-gitlab-ci-yaml"><a href="#关于-gitlab-ci-yaml" class="headerlink" title="关于.gitlab-ci.yaml"></a>关于.gitlab-ci.yaml</h2><ul>
<li><p>支持模板继承</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">.product: &amp;prod_template</span><br><span class="line">  only:</span><br><span class="line">    - master</span><br><span class="line">  retry:</span><br><span class="line">    2</span><br><span class="line"></span><br><span class="line">.rollin: &amp;rollin_template</span><br><span class="line">  &lt;&lt;: *prod_template</span><br><span class="line">  stage: rollin</span><br><span class="line">  script:</span><br><span class="line">  - init_kube_config</span><br><span class="line">  - check_kube_domain</span><br><span class="line">  - ensure_namespace</span><br><span class="line">  - create_secret</span><br><span class="line">  - check_chart</span><br><span class="line">  - deploy canary $ROLLIN_PERCENTAGE</span><br><span class="line">  environment:</span><br><span class="line">    name: $CI_PROJECT_NAME</span><br><span class="line">    url: http://$CI_PROJECT_NAME.test.com</span><br><span class="line"></span><br><span class="line">deploy_canary:</span><br><span class="line">  &lt;&lt;: *rollin_template</span><br><span class="line">  stage: canary</span><br><span class="line">  variables:</span><br><span class="line">    ROLLIN_PERCENTAGE: $CANARY_WEITHG</span><br></pre></td></tr></table></figure>
</li>
<li><p>支持include</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">stages:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">build</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">test</span></span><br><span class="line"><span class="attr">include:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">template:</span> <span class="string">jobs/build.gitlab-ci.yml</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">template:</span> <span class="string">jobs/test.gitlab-ci.yml</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>支持函数定义</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">test:</span><br><span class="line">  stage: test</span><br><span class="line">  image: registry.local/alpine:latest</span><br><span class="line">  script:</span><br><span class="line">    - hello</span><br><span class="line">.auto_devops: &amp;auto_devops |</span><br><span class="line">  export CI_WORD=&quot;hello gitlab ci!</span><br><span class="line">  function hello() &#123;</span><br><span class="line">    echo $CI_WORD</span><br><span class="line">  &#125;</span><br><span class="line">before_script:</span><br><span class="line">  - *auto_devops</span><br></pre></td></tr></table></figure></li>
</ul>

        
    

    
</div>


                

                <!-- Post Comments -->
                
                    
                
            </div>

            <!-- Post Prev & Next Nav -->
            <nav class="material-nav mdl-color-text--grey-50 mdl-cell mdl-cell--12-col">
    <!-- Prev Nav -->
    
        <a href="/rubin-blog/2019/11/06/聊聊红黑树和跳表/" id="post_nav-newer" class="prev-content">
            <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon mdl-color--white mdl-color-text--grey-900" role="presentation">
                <i class="material-icons">arrow_back</i>
            </button>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            新篇
        </a>
    

    <!-- Section Spacer -->
    <div class="section-spacer"></div>

    <!-- Next Nav -->
    
        <a href="/rubin-blog/2019/10/26/Redis的一些理解/" id="post_nav-older" class="next-content">
            旧篇
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon mdl-color--white mdl-color-text--grey-900" role="presentation">
                <i class="material-icons">arrow_forward</i>
            </button>
        </a>
    
</nav>

        </div>
    </div>



                    
                        <!-- Overlay For Active Sidebar -->
<div class="sidebar-overlay"></div>

<!-- Material sidebar -->
<aside id="sidebar" class="sidebar sidebar-colored sidebar-fixed-left" role="navigation">
    <div id="sidebar-main">
        <!-- Sidebar Header -->
        <div class="sidebar-header header-cover" style="background-image: url(/rubin-blog/img/sidebar_header.png);">
    <!-- Top bar -->
    <div class="top-bar"></div>

    <!-- Sidebar toggle button -->
    <button type="button" class="sidebar-toggle mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon" style="display: initial;" data-upgraded=",MaterialButton,MaterialRipple">
        <i class="material-icons">clear_all</i>
        <span class="mdl-button__ripple-container">
            <span class="mdl-ripple">
            </span>
        </span>
    </button>

    <!-- Sidebar Avatar -->
    <div class="sidebar-image">
        <img src="/rubin-blog/img/avatar.jpg" alt="noir's avatar">
    </div>

    <!-- Sidebar Email -->
    <a data-toggle="dropdown" class="sidebar-brand" href="#settings-dropdown">
        noir-lattice@outlook.com
        <b class="caret"></b>
    </a>
</div>


        <!-- Sidebar Navigation  -->
        <ul class="nav sidebar-nav">
    <!-- User dropdown  -->
    <li class="dropdown">
        <ul id="settings-dropdown" class="dropdown-menu">
            
                <li>
                    <a href="#" target="_blank" title="Email Me">
                        
                            <i class="material-icons sidebar-material-icons sidebar-indent-left1pc-element">email</i>
                        
                        Email Me
                    </a>
                </li>
            
        </ul>
    </li>

    <!-- Homepage -->
    
        <li id="sidebar-first-li">
            <a href="/rubin-blog/">
                
                    <i class="material-icons sidebar-material-icons">home</i>
                
                主页
            </a>
        </li>
        
    

    <!-- Archives  -->
    
        <li class="dropdown">
            <a href="#" class="ripple-effect dropdown-toggle" data-toggle="dropdown">
                
                    <i class="material-icons sidebar-material-icons">inbox</i>
                
                    归档
                <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
            <li>
                <a class="sidebar_archives-link" href="/rubin-blog/archives/2020/10/">十月 2020<span class="sidebar_archives-count">3</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/archives/2020/08/">八月 2020<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/archives/2020/07/">七月 2020<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/archives/2020/05/">五月 2020<span class="sidebar_archives-count">6</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/archives/2019/11/">十一月 2019<span class="sidebar_archives-count">3</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/archives/2019/10/">十月 2019<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/archives/2019/09/">九月 2019<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/archives/2019/08/">八月 2019<span class="sidebar_archives-count">5</span></a>
            </ul>
        </li>
        
    

    <!-- Categories  -->
    
        <li class="dropdown">
            <a href="#" class="ripple-effect dropdown-toggle" data-toggle="dropdown">
                
                    <i class="material-icons sidebar-material-icons">chrome_reader_mode</i>
                
                分类
                <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
                <li>
                <a class="sidebar_archives-link" href="/rubin-blog/categories/devops/">devops<span class="sidebar_archives-count">4</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/categories/java/">java<span class="sidebar_archives-count">4</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/categories/kubernetes/">kubernetes<span class="sidebar_archives-count">3</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/categories/中间件/">中间件<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/categories/杂谈/">杂谈<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/categories/架构/">架构<span class="sidebar_archives-count">4</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/categories/算法与数据结构/">算法与数据结构<span class="sidebar_archives-count">3</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/categories/缓存中间件/">缓存中间件<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/categories/网络/">网络<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/rubin-blog/categories/面试/">面试<span class="sidebar_archives-count">1</span></a>
            </ul>
        </li>
        
    

    <!-- Pages  -->
    

    <!-- Article Number  -->
    
        <li>
            <a href="/archives">
                文章总数
                <span class="sidebar-badge">23</span>
            </a>
        </li>
        
    
</ul>


        <!-- Sidebar Footer -->
        <!--
I'm glad you use this theme, the development is no so easy, I hope you can keep the copyright, I will thank you so much.
If you still want to delete the copyrights, could you still retain the first one? Which namely "Theme Material"
It will not impact the appearance and can give developers a lot of support :)

很高兴您使用并喜欢该主题，开发不易 十分谢谢与希望您可以保留一下版权声明。
如果您仍然想删除的话 能否只保留第一项呢？即 "Theme Material"
它不会影响美观并可以给开发者很大的支持和动力。 :)
-->

<!-- Sidebar Divider -->

    <div class="sidebar-divider"></div>


<!-- Theme Material -->
<!-- 
    <a href="https://github.com/viosey/hexo-theme-material"  class="sidebar-footer-text-a" target="_blank">
        <div class="sidebar-text mdl-button mdl-js-button mdl-js-ripple-effect sidebar-footer-text-div" data-upgraded=",MaterialButton,MaterialRipple">
            主题 - Material
            <span class="sidebar-badge badge-circle">i</span>
        </div>
    </a>
 -->

<!-- Help & Support -->
<!--

-->

<!-- Feedback -->
<!--

-->

<!-- About Theme -->
<!--

-->

    </div>

    <!-- Sidebar Image -->
    

</aside>

                    

                    
                        <!-- Footer Top Button -->
                        <div id="back-to-top" class="toTop-wrap">
    <a href="#top" class="toTop">
        <i class="material-icons footer_top-i">expand_less</i>
    </a>
</div>

                    

                    <!--Footer-->
<footer class="mdl-mini-footer" id="bottom">
    
        <!-- Paradox Footer Left Section -->
        <div class="mdl-mini-footer--left-section sns-list">
    <!-- Twitter -->
    

    <!-- Facebook -->
    

    <!-- Google + -->
    

    <!-- Weibo -->
    

    <!-- Instagram -->
    

    <!-- Tumblr -->
    

    <!-- Github -->
    
        <a href="https://github.com/noir-lattice" target="_blank">
            <button class="mdl-mini-footer--social-btn social-btn footer-sns-github">
                <span class="visuallyhidden">Github</span>
            </button><!--
     --></a>
    

    <!-- LinkedIn -->
    

    <!-- Zhihu -->
    

    <!-- Bilibili -->
    
        <a href="https://space.bilibili.com/2006225" target="_blank">
            <button class="mdl-mini-footer--social-btn social-btn footer-sns-bilibili">
                <span class="visuallyhidden">Bilibili</span>
            </button><!--
     --></a>
    

    <!-- Telegram -->
    

    <!-- V2EX -->
    

    <!-- Segmentfault -->
    
</div>


        <!--Copyright-->
        <div id="copyright">
            Copyright&nbsp;©&nbsp;<span year></span>&nbsp;Noir的博客
            
        </div>

        <!-- Paradox Footer Right Section -->

        <!--
        I am glad you use this theme, the development is no so easy, I hope you can keep the copyright.
        It will not impact the appearance and can give developers a lot of support :)

        很高兴您使用该主题，开发不易，希望您可以保留一下版权声明。
        它不会影响美观并可以给开发者很大的支持。 :)
        -->

        <div class="mdl-mini-footer--right-section">
            <div>
                <div class="footer-develop-div">Powered by <a href="https://hexo.io" target="_blank" class="footer-develop-a">Hexo</a></div>
                <div class="footer-develop-div">Theme - <a href="https://github.com/viosey/hexo-theme-material" target="_blank" class="footer-develop-a">Material</a></div>
            </div>
        </div>
    
</footer>


                    <!-- Import JS File -->

    <script>lsloader.load("lazyload_js","/rubin-blog/js/lazyload.min.js?wgjW/HuQG9JDgvPDPoRAng==", true)</script>



    <script>lsloader.load("js_js","/rubin-blog/js/js.min.js?LT4t6iE6m8TO1BLGGiNJqA==", true)</script>



    <script>lsloader.load("np_js","/rubin-blog/js/nprogress.js?pl3Qhb9lvqR1FlyLUna1Yw==", true)</script>


<script type="text/ls-javascript" id="NProgress-script">
    NProgress.configure({
        showSpinner: true
    });
    NProgress.start();
    $('#nprogress .bar').css({
        'background': '#29d'
    });
    $('#nprogress .peg').css({
        'box-shadow': '0 0 10px #29d, 0 0 15px #29d'
    });
    $('#nprogress .spinner-icon').css({
        'border-top-color': '#29d',
        'border-left-color': '#29d'
    });
    setTimeout(function() {
        NProgress.done();
        $('.fade').removeClass('out');
    }, 800);
</script>













<!-- UC Browser Compatible -->
<script>
	var agent = navigator.userAgent.toLowerCase();
	if(agent.indexOf('ucbrowser')>0) {
		document.write('<link rel="stylesheet" href="/rubin-blog/css/uc.css">');
	   alert('由于 UC 浏览器使用极旧的内核，而本网站使用了一些新的特性。\n为了您能更好的浏览，推荐使用 Chrome 或 Firefox 浏览器。');
	}
</script>

<!-- Import prettify js  -->



<!-- Window Load -->
<!-- add class for prettify -->
<script type="text/ls-javascript" id="window-load">
    $(window).on('load', function() {
        // Post_Toc parent position fixed
        $('.post-toc-wrap').parent('.mdl-menu__container').css('position', 'fixed');
    });

    
    
</script>

<!-- MathJax Load-->


<!-- Bing Background -->


<script type="text/ls-javascript" id="lazy-load">
    // Offer LazyLoad
    queue.offer(function(){
        $('.lazy').lazyload({
            effect : 'show'
        });
    });

    // Start Queue
    $(document).ready(function(){
        setInterval(function(){
            queue.execNext();
        },200);
    });
</script>

<!-- Custom Footer -->



<script>
    var copyrightNow = new Date().getFullYear();
    var textContent = document.querySelector('span[year]')

    copyrightSince = 0000;
    if (copyrightSince === copyrightNow||copyrightSince === 0000) {
        textContent.textContent = copyrightNow
    } else {
        textContent.textContent = copyrightSince + ' - ' + copyrightNow
    }

    (function(){
        var scriptList = document.querySelectorAll('script[type="text/ls-javascript"]')

        for (var i = 0; i < scriptList.length; ++i) {
            var item = scriptList[i];
            lsloader.runInlineScript(item.id,item.id);
        }
    })()
console.log('\n %c © Material Theme | Version: 1.5.6 | https://github.com/viosey/hexo-theme-material %c \n', 'color:#455a64;background:#e0e0e0;padding:5px 0;border-top-left-radius:5px;border-bottom-left-radius:5px;', 'color:#455a64;background:#e0e0e0;padding:5px 0;border-top-right-radius:5px;border-bottom-right-radius:5px;');
</script>

                </main>
            </div>
        </body>
    
    <link  href="/rubin-blog/css/viewer.min.css" rel="stylesheet">
    <script src="/rubin-blog/js/viewer.min.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        //默认设置， 可以根据个人需求和喜好进行配置
        //详细参考官方说明
        Viewer.setDefaults({
            //设置初始缩放 default: 1
            zoomRatio : [0.5],
            //设置滚轮缩放比率 default: 0.1
            show: function () {
              this.viewer.zoomTo(0.5);
            },
          });
        //获得content中所有的图片， 不同主题可能有所不同
        //为了和其他的图片区别开来 所以在markdown中插入图片的时候使用独特的记号
        var imageList = document.getElementsByTagName("img");
        //将获取到的HTMLCollections转化成Array
        var imageArray = new Array();
        Array.prototype.forEach.call(imageList, element => {
          imageArray.push(element);
        });
        //设置每个图片成为图片组
        Array.prototype.forEach.call(imageList, element => {
          var viewer1 = new Viewer(element);
          viewer1.images = imageArray;
          viewer1.length = imageArray.length;
        });
    </script>
</html>
